/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */
#pragma once

#include <string>
#include <ctype.h>
#include <vector>

#ifdef SAMSUNG_VERSION
#include <stddef.h>	//for size_t on Samsung
#endif

namespace liba
{

/** This namespace contains {@link #convert} function, used to convert
	any type to the sequence of characters and vice versa. It is used widely 
	by generic (template-based) services, such as logging, XML loading/saving,
	Unicode/ANSI convertsion, etc. The most important template in this 
	namespace is the ConverterTraits. You specialize ConverterTraits for your 
	own	types, thus teaching them to convert to sequences of characters. 
	Usually you use ANSI and Unicode sequences, but you can use the other 
	symbol type, if you need. For most types ConverterTraits use buffers
	allocated in the stack, making conversion very effective.
	Microsoft Visual Studio 6 does not support partial specialization and you 
	are limited to ANSI and Unicode characters, if you use MSVC6. */
namespace converter
{

template<class Dst>
struct ConverterBestCharSelector
{
        typedef void BestChar;
};

template<>
struct ConverterBestCharSelector< std::basic_string<char> >
{
	typedef char BestChar;
};

template<>
struct ConverterBestCharSelector< std::basic_string<wchar_t> >
{
	typedef wchar_t BestChar;
};

template<class Sym, class Dst>
struct ConverterTraits
{
	typedef typename Dst::template ConverterBuffer<Sym> Buffer;

	template<class FromSym>
	static bool convert(const FromSym * be, const FromSym * en, Dst * dst)
	{
		return dst->convert( be, en );
	}
};

template<class S1, class S2>
struct Helper
{
	template<class Src, class Dst>
	static bool convert_helper(const Src & from, Dst * to)
	{
		typedef typename ConverterTraits<S1, Src>::Buffer ConverterBuffer;
		typedef ConverterTraits<S1, Dst> DstTraits;
		ConverterBuffer con_buf;
		if( !con_buf.convert( from ) )
			return false;
		return DstTraits::convert( con_buf.begin(), con_buf.end(), to );
	}
};

template<class S1>
struct Helper<S1, void>
{
	template<class Src, class Dst>
	static bool convert_helper(const Src & from, Dst * to)
	{
		typedef typename ConverterTraits<S1, Src>::Buffer ConverterBuffer;
		typedef ConverterTraits<S1, Dst> DstTraits;
		ConverterBuffer con_buf;
		if( !con_buf.convert( from ) )
			return false;
		return DstTraits::convert( con_buf.begin(), con_buf.end(), to );
	}
};

template<class S2>
struct Helper<void, S2>
{
	template<class Src, class Dst>
	static bool convert_helper(const Src & from, Dst * to)
	{
		typedef typename ConverterTraits<S2, Src>::Buffer ConverterBuffer;
		typedef ConverterTraits<S2, Dst> DstTraits;
		ConverterBuffer con_buf;
		if( !con_buf.convert( from ) )
			return false;
		return DstTraits::convert( con_buf.begin(), con_buf.end(), to );
	}
};

template<>
struct Helper<void, void>
{
	template<class Src, class Dst>
	static bool convert_helper(const Src & from, Dst * to)
	{
		typedef typename ConverterTraits<char, Src>::Buffer ConverterBuffer;
		typedef ConverterTraits<char, Dst> DstTraits;
		ConverterBuffer con_buf;
		if( !con_buf.convert( from ) )
			return false;
		return DstTraits::convert( con_buf.begin(), con_buf.end(), to );
	}
};

template<class Src, class Dst>
bool convert(const Src & from, Dst * to)
{
	typedef typename ConverterBestCharSelector<Src>::BestChar SrcSym;
	typedef typename ConverterBestCharSelector<Dst>::BestChar DstSym;
	typedef Helper<SrcSym,DstSym> Help;
	return Help::convert_helper( from, to );
}

} // namespace converter
} // namespace liba

using namespace liba;

#include "ConverterImpl.h"
